package com.ruoyi.business.service.wecom.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.business.domain.wecom.*;
import com.ruoyi.business.service.wecom.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.wecom.WecomChatGroupStatusEnum;
import com.ruoyi.common.enums.wecom.WecomCustomerStatusEnum;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.external.WxCpUserExternalGroupChatInfo;
import me.chanjar.weixin.cp.bean.external.WxCpUserExternalGroupChatList;
import me.chanjar.weixin.cp.bean.external.contact.ExternalContact;
import me.chanjar.weixin.cp.bean.external.contact.FollowedUser;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactBatchInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Slf4j
@Service
public class WecomDataDellServiceImpl implements WecomDataDellService {

    @Resource
    private WxCpService wxCpService;

    @Resource
    private ITbWecomExternalContactFollowUserService wecomExternalContactFollowUserService;

    @Resource
    private ITbWecomChatGroupService wecomChatGroupService;

    @Resource
    private ITbWecomChatGroupMemberService wecomChatGroupMemberService;

    @Resource
    private ITbWecomTagGroupService tbWecomTagGroupService;

    @Resource
    private ITbWecomExternalContactCustomerService tbWecomExternalContactCustomerService;

    @Resource
    private ITbWecomExternalContactCustomerFollowUserService tbWecomExternalContactCustomerFollowUserService;

    @Resource
    private ITbWecomExternalContactCustomerFollowUserTagService tbWecomExternalContactCustomerFollowUserTagService;

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Value("${wechat.cp.apps[0].agent-id}")
    private String agentId;


    @Override
    public void dellWecomData() {
        long startTime = System.currentTimeMillis();
        log.info("开始同步企业微信数据...");
        // 1. 先同步基础数据（串行执行）
        wecomExternalContactFollowUserService.sysSyncWecomExternalContactFollowUserData();
        tbWecomTagGroupService.sysSyncWecomTagData();
        try {
            // 2. 并行执行客户和群组数据同步
            CompletableFuture<Void> customerFuture = CompletableFuture.runAsync(() -> {
                log.info("开始同步客服外部联系人信息...");
                this.wecomCustomerHandel();
                log.info("客服外部联系人信息同步完成");
            }, threadPoolTaskExecutor).exceptionally(e -> {
                log.error("同步客服外部联系人信息失败: {}", e.getMessage());
                return null;
            });

            CompletableFuture<Void> groupFuture = CompletableFuture.runAsync(() -> {
                log.info("开始同步群聊成员信息...");
                this.wecomGroupHandler();
                log.info("群聊成员信息同步完成");
            }, threadPoolTaskExecutor).exceptionally(e -> {
                log.error("同步群聊成员信息失败: {}", e.getMessage());
                return null;
            });
            // 3. 等待所有并行任务完成
            CompletableFuture.allOf(customerFuture, groupFuture).join();
            log.info("企业微信数据同步完成，总耗时: {}ms", System.currentTimeMillis() - startTime);
        } catch (Exception e) {
            log.error("企业微信数据同步过程中发生异常: {}", e.getMessage());
            throw new RuntimeException("企业微信数据同步失败", e);
        }
    }

    // 同步客户数据
    private void wecomCustomerHandel() {
        // 查询数据库中是否存在数据如果存在就跳过数据同步
        long count = tbWecomExternalContactCustomerService.count();
        if (count == 0) {
            WxCpExternalContactService externalContactService = wxCpService.getExternalContactService();
            List<TbWecomExternalContactFollowUser> tbWecomExternalContactFollowUserList = wecomExternalContactFollowUserService.list();
            for (TbWecomExternalContactFollowUser tbWecomExternalContactFollowUser : tbWecomExternalContactFollowUserList) {
                processSingleFollowUser(externalContactService, tbWecomExternalContactFollowUser);
            }
        }
    }

    private void processSingleFollowUser(WxCpExternalContactService externalContactService,
                                         TbWecomExternalContactFollowUser followUser) {
        List<String> userIds = Collections.singletonList(followUser.getUserId());
        String cursor = StrUtil.EMPTY;
        try {
            do {
                WxCpExternalContactBatchInfo contactDetailBatch = externalContactService.getContactDetailBatch(
                    userIds.toArray(new String[0]), cursor, 100);
                // 处理当前批次数据
                processContactDetailBatch(contactDetailBatch);
                // 检查是否还有更多数据
                cursor = contactDetailBatch.getNextCursor();
            } while (!StringUtils.isEmpty(cursor));
        } catch (WxErrorException e) {
            log.error("批量获取客户详情失败: userId={}", followUser.getUserId());
            throw new RuntimeException("批量获取客户详情失败: " + followUser.getUserId(), e);
        }
    }

    private void processContactDetailBatch(WxCpExternalContactBatchInfo contactDetailBatch) {
        if (ObjectUtil.isEmpty(contactDetailBatch) || CollectionUtils.isEmpty(contactDetailBatch.getExternalContactList())) {
            return;
        }
        // 批量处理客户数据
        List<TbWecomExternalContactCustomer> customersToSave = new ArrayList<>();
        List<TbWecomExternalContactCustomerFollowUser> followUsersToSave = new ArrayList<>();
        List<TbWecomExternalContactCustomerFollowUserTag> tagsToSave = new ArrayList<>();
        for (WxCpExternalContactBatchInfo.ExternalContactInfo externalContactInfo : contactDetailBatch.getExternalContactList()) {
            // 客户信息
            ExternalContact externalContact = externalContactInfo.getExternalContact();
            // 客服信息
            FollowedUser followInfo = externalContactInfo.getFollowInfo();
            String externalUserId = externalContact.getExternalUserId();
            // 检查客户是否存在
            boolean customerExists = isCustomerExists(externalUserId);
            if (customerExists) {
                // 处理跟进人更新
                processFollowUsersForExistingCustomer(externalUserId, followInfo, followUsersToSave, tagsToSave);
            } else {
                // 新增客户
                TbWecomExternalContactCustomer customer = buildCustomerEntity(externalContact);
                customersToSave.add(customer);
                // 处理跟进人和标签
                processFollowUsersForNewCustomer(externalUserId, followInfo, followUsersToSave, tagsToSave);
            }
        }
        // 批量执行数据库操作
        executeBatchOperations(customersToSave, followUsersToSave, tagsToSave);
    }

    private boolean isCustomerExists(String externalUserId) {
        return tbWecomExternalContactCustomerService.count(
            Wrappers.lambdaQuery(TbWecomExternalContactCustomer.class)
                .eq(TbWecomExternalContactCustomer::getExternalUserid, externalUserId)
        ) > 0;
    }

    private TbWecomExternalContactCustomer buildCustomerEntity(ExternalContact externalContact) {
        TbWecomExternalContactCustomer customer = new TbWecomExternalContactCustomer();
        customer.setId(IdWorker.getId());
        customer.setExternalUserid(externalContact.getExternalUserId());
        customer.setName(externalContact.getName());
        customer.setAvatar(externalContact.getAvatar());
        customer.setType(externalContact.getType());
        customer.setGender(externalContact.getGender());
        customer.setUnionid(externalContact.getUnionId());
        customer.setPosition(externalContact.getPosition());
        customer.setCorpName(externalContact.getCorpName());
        customer.setCorpFullName(externalContact.getCorpFullName());
        customer.setCreateTime(new Date());
        customer.setUpdateTime(new Date()); // 添加更新时间
        return customer;
    }

    private void processFollowUsersForNewCustomer(String externalUserId, FollowedUser followedUser,
                                                  List<TbWecomExternalContactCustomerFollowUser> followUsersToSave,
                                                  List<TbWecomExternalContactCustomerFollowUserTag> tagsToSave) {

        TbWecomExternalContactCustomerFollowUser followUserEntity = buildFollowUserEntity(externalUserId, followedUser);
        followUsersToSave.add(followUserEntity);
        // 处理标签
        if (ObjectUtil.isNotEmpty(followedUser.getTagIds())) {
            processTagsForFollowUser(externalUserId, followedUser, tagsToSave);
        }

    }

    private void processFollowUsersForExistingCustomer(String externalUserId, FollowedUser followedUser,
                                                       List<TbWecomExternalContactCustomerFollowUser> followUsersToSave,
                                                       List<TbWecomExternalContactCustomerFollowUserTag> tagsToSave) {

        // 检查跟进人关系是否已存在
        boolean followUserExists = tbWecomExternalContactCustomerFollowUserService.count(
            Wrappers.lambdaQuery(TbWecomExternalContactCustomerFollowUser.class)
                .eq(TbWecomExternalContactCustomerFollowUser::getExternalUserid, externalUserId)
                .eq(TbWecomExternalContactCustomerFollowUser::getUserId, followedUser.getUserId())
                .eq(TbWecomExternalContactCustomerFollowUser::getStatus, WecomCustomerStatusEnum.NOT_LOST.getCode())
        ) > 0;

        if (!followUserExists) {
            // 不存在客户联系关系
            TbWecomExternalContactCustomerFollowUser followUserEntity = buildFollowUserEntity(externalUserId, followedUser);
            followUsersToSave.add(followUserEntity);
            // 处理标签
            if (ObjectUtil.isNotEmpty(followedUser.getTagIds())) {
                processTagsForFollowUser(externalUserId, followedUser, tagsToSave);
            }
        }

    }

    private TbWecomExternalContactCustomerFollowUser buildFollowUserEntity(String externalUserId, FollowedUser followedUser) {
        TbWecomExternalContactCustomerFollowUser entity = new TbWecomExternalContactCustomerFollowUser();
        entity.setId(IdWorker.getId());
        entity.setExternalUserid(externalUserId);
        entity.setUserId(followedUser.getUserId());
        entity.setRemark(followedUser.getRemark());
        entity.setDescription(followedUser.getDescription());
        entity.setAddTime(followedUser.getCreateTime());
        entity.setRemarkCorpName(followedUser.getRemarkCorpName());
        entity.setRemarkMobiles(String.join(",", followedUser.getRemarkMobiles()));
        entity.setAddWay(parseAddWay(followedUser.getAddWay()));
        entity.setOperUserid(followedUser.getOperatorUserId());
        entity.setState(followedUser.getState());
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        // 处理视频号信息
        handleWechatChannelsInfo(entity, followedUser.getWechatChannels());
        // 处理标签ID
        if (ObjectUtil.isNotEmpty(followedUser.getTagIds())) {
            entity.setTagIds(String.join(",", followedUser.getTagIds()));
        }
        return entity;
    }

    private void processTagsForFollowUser(String externalUserId, FollowedUser followedUser,
                                          List<TbWecomExternalContactCustomerFollowUserTag> tagsToSave) {
        List<String> tagIds = Arrays.asList(followedUser.getTagIds());
        tagIds.forEach(tagId -> {
            TbWecomExternalContactCustomerFollowUserTag tagEntity = new TbWecomExternalContactCustomerFollowUserTag();
            tagEntity.setId(IdWorker.getId());
            tagEntity.setExternalUserid(externalUserId);
            tagEntity.setUserId(followedUser.getUserId());
            tagEntity.setTagId(tagId);
            tagEntity.setCreateTime(new Date());
            tagsToSave.add(tagEntity);
        });
    }


    private Integer parseAddWay(String addWay) {
        try {
            return Integer.valueOf(addWay);
        } catch (NumberFormatException e) {
            log.warn("无效的添加方式: {}", addWay);
            return 0;
        }
    }

    private void handleWechatChannelsInfo(TbWecomExternalContactCustomerFollowUser entity,
                                          FollowedUser.WechatChannels wechatChannels) {
        if (ObjectUtil.isNotEmpty(wechatChannels)) {
            entity.setWechatChannelsNickname(wechatChannels.getNickname());
            entity.setWechatChannelsSource(wechatChannels.getSource());
        }
    }

    private void executeBatchOperations(List<TbWecomExternalContactCustomer> customersToSave,
                                        List<TbWecomExternalContactCustomerFollowUser> followUsersToSave,
                                        List<TbWecomExternalContactCustomerFollowUserTag> tagsToSave) {
        // 批量保存新客户
        if (CollectionUtils.isNotEmpty(customersToSave)) {
            tbWecomExternalContactCustomerService.saveBatch(customersToSave);
            log.info("批量保存新客户数量: {}", customersToSave.size());
        }

        // 批量保存跟进人关系
        if (CollectionUtils.isNotEmpty(followUsersToSave)) {
            tbWecomExternalContactCustomerFollowUserService.saveBatch(followUsersToSave);
            log.info("批量保存跟进人关系数量: {}", followUsersToSave.size());
        }

        // 批量保存标签关系
        if (CollectionUtils.isNotEmpty(tagsToSave)) {
            tbWecomExternalContactCustomerFollowUserTagService.saveBatch(tagsToSave);
            log.info("批量保存标签关系数量: {}", tagsToSave.size());
        }
    }

    // 同步群组 - 只处理数据库中不存在的群聊
    private void wecomGroupHandler() {
        // 查询
        long count = wecomChatGroupService.count();
        if (count == 0) {
            WxCpExternalContactService externalContactService = wxCpService.getExternalContactService();
            String cursor = StrUtil.EMPTY;
            try {
                do {
                    WxCpUserExternalGroupChatList wxCpUserExternalGroupChatList = externalContactService.listGroupChat(100, cursor, WecomChatGroupStatusEnum.NORMAL.getCode(), null);
                    processGroupBatch(wxCpUserExternalGroupChatList, externalContactService);
                    // 检查是否还有更多数据
                    cursor = wxCpUserExternalGroupChatList.getNextCursor();
                } while (!StringUtils.isEmpty(cursor));
            } catch (WxErrorException e) {
                log.error("同步群组失败");
                throw new RuntimeException(e);
            }
        }
    }

    private void processGroupBatch(WxCpUserExternalGroupChatList wxCpUserExternalGroupChatList, WxCpExternalContactService externalContactService) {
        if (CollectionUtils.isEmpty(wxCpUserExternalGroupChatList.getGroupChatList())) {
            return;
        }
        List<List<WxCpUserExternalGroupChatList.ChatStatus>> chatGroupList = ListUtil.partition(wxCpUserExternalGroupChatList.getGroupChatList(), 10);
        chatGroupList.forEach(batch -> {
            // 获取当前批次的chatId集合
            Set<String> batchChatIds = batch.stream().map(WxCpUserExternalGroupChatList.ChatStatus::getChatId).collect(Collectors.toSet());
            // 查询数据库中已存在的群聊
            List<TbWecomChatGroup> existingGroups = wecomChatGroupService.list(Wrappers.lambdaQuery(TbWecomChatGroup.class).in(TbWecomChatGroup::getChatId, batchChatIds));
            // 提取已存在的chatId
            Set<String> existingChatIds = existingGroups.stream().map(TbWecomChatGroup::getChatId).collect(Collectors.toSet());
            // 筛选出数据库中不存在的群聊
            List<WxCpUserExternalGroupChatList.ChatStatus> newChatGroups = batch.stream().filter(chat -> !existingChatIds.contains(chat.getChatId())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(newChatGroups)) {
                return;
            }
            // 批量处理新群聊
            processNewChatGroups(newChatGroups, externalContactService);
        });
    }

    /**
     * 处理新群聊数据
     */
    private void processNewChatGroups(List<WxCpUserExternalGroupChatList.ChatStatus> newChatGroups, WxCpExternalContactService externalContactService) {
        List<TbWecomChatGroup> groupsToInsert = new ArrayList<>();
        List<TbWecomChatGroupMember> allMembersToInsert = new ArrayList<>();
        for (WxCpUserExternalGroupChatList.ChatStatus chatStatus : newChatGroups) {
            String chatId = chatStatus.getChatId();
            try {
                // 获取群详情
                WxCpUserExternalGroupChatInfo groupChatInfo = externalContactService.getGroupChat(chatId, Constants.TRUE_1);
                // 构建群聊实体
                TbWecomChatGroup chatGroup = buildChatGroup(chatStatus, groupChatInfo);
                groupsToInsert.add(chatGroup);
                // 构建群成员列表
                List<TbWecomChatGroupMember> members = buildChatGroupMembers(chatId, groupChatInfo);
                allMembersToInsert.addAll(members);
            } catch (WxErrorException e) {
                log.error("获取群聊详情失败, chatId: {}", chatId, e);
            }
        }

        // 批量插入群聊数据
        if (!groupsToInsert.isEmpty()) {
            wecomChatGroupService.saveBatch(groupsToInsert);
            log.info("批量插入新群聊数量: {}", groupsToInsert.size());
        }

        // 批量插入群成员数据
        if (!allMembersToInsert.isEmpty()) {
            wecomChatGroupMemberService.saveBatch(allMembersToInsert);
            log.info("批量插入群成员数量: {}", allMembersToInsert.size());
        }
    }

    /**
     * 构建完整的群聊实体
     */
    private TbWecomChatGroup buildChatGroup(WxCpUserExternalGroupChatList.ChatStatus chatStatus, WxCpUserExternalGroupChatInfo groupChatInfo) {
        WxCpUserExternalGroupChatInfo.GroupChat groupChat = groupChatInfo.getGroupChat();
        TbWecomChatGroup entity = new TbWecomChatGroup();
        entity.setId(IdWorker.getId());
        entity.setAgentId(agentId);
        entity.setChatId(chatStatus.getChatId());
        entity.setStatus(chatStatus.getStatus());
        entity.setChatName(StringUtils.isNotEmpty(groupChat.getName()) ? groupChat.getName() : "");
        entity.setChatOwner(StringUtils.isNotEmpty(groupChat.getOwner()) ? groupChat.getOwner() : "");
        entity.setChatCreateTime(groupChat.getCreateTime());
        entity.setChatNotice(StringUtils.isNotEmpty(groupChat.getNotice()) ? groupChat.getNotice() : "");
        entity.setMemberNum(groupChat.getMemberList().size());
        entity.setAdminUserIds(groupChat.getAdminList().stream().map(WxCpUserExternalGroupChatInfo.GroupAdmin::getUserId).collect(Collectors.joining(",")));
        entity.setMemberVersion(groupChat.getMemberVersion());
        return entity;
    }

    /**
     * 构建群成员列表
     */
    private List<TbWecomChatGroupMember> buildChatGroupMembers(String chatId, WxCpUserExternalGroupChatInfo groupChatInfo) {
        List<TbWecomChatGroupMember> members = new ArrayList<>();
        groupChatInfo.getGroupChat().getMemberList().forEach(member -> {
            TbWecomChatGroupMember memberEntity = new TbWecomChatGroupMember();
            memberEntity.setId(IdWorker.getId());
            memberEntity.setChatId(chatId);
            memberEntity.setUserId(member.getUserId());
            memberEntity.setUserType(member.getType());
            memberEntity.setUserUnionid(member.getUnionId());
            memberEntity.setJoinTime(member.getJoinTime());
            memberEntity.setJoinScene(member.getJoinScene());
            memberEntity.setInvitorUserIds(member.getInvitor() != null ? member.getInvitor().getUserId() : "");
            memberEntity.setGroupNickname(member.getGroupNickname());
            memberEntity.setName(StringUtils.isNotEmpty(member.getName()) ? member.getName() : "");
            memberEntity.setState(StringUtils.isNotEmpty(member.getState()) ? member.getState() : "");
            memberEntity.setCreateTime(new Date());
            memberEntity.setUpdateTime(new Date());
            members.add(memberEntity);
        });
        return members;
    }

}
